package com.fiberhome.app.network.http;


import android.text.TextUtils;

import com.fiberhome.app.network.CallBack;
import com.fiberhome.app.network.Failure;
import com.fiberhome.app.network.IData;
import com.fiberhome.app.network.cache.CacheUtil;
import com.fiberhome.app.network.cache.CacheBean;
import com.fiberhome.app.network.parse.Parser;

import java.io.IOException;
import java.util.Map;

import io.reactivex.Observable;
import io.reactivex.ObservableEmitter;
import io.reactivex.ObservableOnSubscribe;
import io.reactivex.ObservableSource;
import io.reactivex.Observer;
import io.reactivex.android.schedulers.AndroidSchedulers;
import io.reactivex.annotations.NonNull;
import io.reactivex.disposables.Disposable;
import io.reactivex.functions.Function;
import io.reactivex.functions.Predicate;
import io.reactivex.schedulers.Schedulers;
import okhttp3.Call;
import okhttp3.FormBody;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;

/**
 * 基于okhttp3封装的http网络请求
 * Created by Deed on 2018/1/10.
 */

class OKHttpSender extends HttpSender {
    /**
     *
     */
    private static OkHttpClient.Builder builder;

    static {
        builder = new OkHttpClient.Builder();
    }

    private OkHttpClient client;

    private Call call;

    private HttpBuilder httpBuilder;

    /**
     * @param builder OkHttpClient.Builder
     * @throws Exception ss
     */
    public static void setBuilder(OkHttpClient.Builder builder) throws Exception {
        if (builder == null) {
            throw new Exception("Null builder set is not allowed");
        }
        OKHttpSender.builder = builder;

    }

    /**
     * return value.
     */
    public static OkHttpClient.Builder getBuilder() {
        return builder;
    }

    /**
     * @param httpBuilder HttpBuilder
     */
    OKHttpSender(@NonNull HttpBuilder httpBuilder) {
        super(httpBuilder);
        this.httpBuilder = httpBuilder;
        client = builder.build();
    }

    @Override
    public void cancel() {
        if (call != null) {
            call.cancel();
        }
    }

    @Override
    protected <T extends IData> IData getRemoteData(Class<T> cls) {
        call = client.newCall(buildRequest());
        IData data;
        try {
            Response res = call.execute();
            if (res.isSuccessful()) {
                if (res.body() != null) {
                    String str = res.body().string();
                    if (!TextUtils.isEmpty(str)) {
                        data = Parser.parseTo(str, cls);
                        if (data == null) {
                            data = new Failure(Failure.ERROR_DATA_PARSE, "Data format invalid");
                        } else {
                            CacheUtil.myCache().put(httpBuilder, data, str);
                        }
                    } else {
                        data = new Failure(Failure.ERROR_DATA_NULL, "Response is empty");
                    }
                } else {
                    data = new Failure(Failure.ERROR_DATA_NULL, "Response is null");
                }
            } else {
                data = new Failure(Failure.ERROR_CONNECT, "Can not connect server");
            }
        } catch (IOException e) {
            e.printStackTrace();
            data = new Failure(Failure.ERROR_CONNECT, "Network is not available");
        }
        return data;
    }

    private Request buildRequest() {
        Request.Builder requestBuilder = new Request.Builder();
        if (httpBuilder.headers != null && httpBuilder.headers.size() > 0) {
            for (Map.Entry<String, String> entry :
                    httpBuilder.headers.entrySet()) {
                requestBuilder.addHeader(entry.getKey(), entry.getValue());
            }
        }
        requestBuilder.url(httpBuilder.url);
        switch (httpBuilder.method) {
            case HttpBuilder.POST:
                FormBody.Builder builder = new FormBody.Builder();
                if (httpBuilder.params != null && httpBuilder.params.size() > 0) {
                    for (Map.Entry<String, String> entry : httpBuilder.params.entrySet()) {
                        builder.add(entry.getKey(), entry.getValue());
                    }
                }
                requestBuilder.post(builder.build());
            case HttpBuilder.GET:
                StringBuilder sb = new StringBuilder();
                if (httpBuilder.params != null && httpBuilder.params.size() > 0) {
                    for (Map.Entry<String, String> entry : httpBuilder.params.entrySet()) {
                        if (sb.length() > 0) {
                            sb.append("&");
                        }
                        sb.append(entry.getKey()).append("=").append(entry.getValue());
                    }
                }
                requestBuilder.url(httpBuilder.url + "?" + sb.toString());
                break;
            default:
                break;
        }

        return requestBuilder.build();
    }

}
